今天,我們來學習 Rust 在網路程式設計中的應用,如何利用 Rust 建構高效能的網路服務與實現網路協議。Rust 的內存安全性與高效能特性,使其成為開發穩定且高效網路應用的理想選擇。
Tokio 是 Rust 生態系統中最流行的非同步運行時之一,特別適合用於網路程式設計。
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
loop {
let n = match socket.read(&mut buf).await {
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
eprintln!("無法讀取資料: {}", e);
return;
}
};
if let Err(e) = socket.write_all(&buf[0..n]).await {
eprintln!("無法寫入資料: {}", e);
return;
}
}
});
}
}
Hyper 是一個快速且正確的 HTTP 實現庫,非常適合用於建立 Web 服務。
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use std::convert::Infallible;
use std::net::SocketAddr;
async fn handle(_: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("Hello, World!")))
}
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let make_svc = make_service_fn(|_conn| async {
Ok::<_, Infallible>(service_fn(handle))
});
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("伺服器錯誤: {}", e);
}
}
gRPC 是一個高效能的 RPC 框架,Tonic 提供了在 Rust 中使用 gRPC 的能力。
use tonic::{transport::Server, Request, Response, Status};
pub mod hello_world {
tonic::include_proto!("helloworld");
}
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
#[derive(Debug, Default)]
pub struct MyGreeter {}
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>,
) -> Result<Response<HelloReply>, Status> {
let reply = hello_world::HelloReply {
message: format!("你好 {}!", request.into_inner().name),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
Server::builder()
.add_service(GreeterServer::new(greeter))
.serve(addr)
.await?;
Ok(())
}
在網路程式設計中,安全性至關重要。Tokio-rustls 提供了非同步 TLS 功能。
use tokio::net::TcpListener;
use tokio_rustls::TlsAcceptor;
use rustls::{Certificate, PrivateKey, ServerConfig};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cert = Certificate(std::fs::read("cert.pem")?);
let key = PrivateKey(std::fs::read("key.pem")?);
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(vec![cert], key)?;
let acceptor = TlsAcceptor::from(Arc::new(config));
let listener = TcpListener::bind("127.0.0.1:8443").await?;
while let Ok((stream, _)) = listener.accept().await {
let acceptor = acceptor.clone();
tokio::spawn(async move {
if let Ok(stream) = acceptor.accept(stream).await {
// 處理加密連接
}
});
}
Ok(())
}
Reqwest 是一個易用的 HTTP 客戶端庫,適合用於發送 HTTP 請求。
use reqwest;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::get("https://www.rust-lang.org")
.await?
.text()
.await?;
println!("回應內容長度: {}", response.len());
Ok(())
}
UDP 通常用於需要低延遲的應用程式,如遊戲或即時流媒體。
use tokio::net::UdpSocket;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
let socket = UdpSocket::bind("127.0.0.1:8080").await?;
let mut buf = [0; 1024];
loop {
let (len, addr) = socket.recv_from(&mut buf).await?;
println!("從 {:?} 收到: {:?}", addr, &buf[..len]);
let len = socket.send_to(&buf[..len], addr).await?;
println!("發送 {} 位元組到 {:?}", len, addr);
}
}
Rust 在網路程式設計中有很大的優勢。它的安全性保證和高效能特性使得開發人員能夠建立可靠、高效的網路服務和協議實現。透過豐富的生態系統,Rust 提供了多種工具和庫來處理各種網路程式設計需求,從低層級的 TCP/UDP 操作到高層級的 HTTP 和 gRPC 服務,之前到量化交易公司面試過,他們也在使用Rust打造他們的量化交易系統,比C++安全和穩定,不過Rust市場是的職缺和開發者在台灣還不是很多,是一個可以投資的副語言。